package generics

import (
	"cmp"
	"sort"
)

type (
	// 比較函數
	LessFunc = func(i, j int) bool

	// TList 任意類型列表
	TList[T comparable] []T
)

// List 構造泛型列表
func List[T comparable](list []T) TList[T] {
	return TList[T](list)
}

// Len 返回長度
func (list TList[T]) Len() int {
	return len(list)
}

// Empty 列表是否爲空
func (list TList[T]) Empty() bool {
	return list.Len() == 0
}

// ForEach 遍歷處理所有鍵值對
func (list TList[T]) ForEach(handle func(index int, value T) error) (succeeded int, err error) {
	for index, value := range list {
		err = handle(index, value)
		if err != nil {
			return
		}
		succeeded++
	}
	return
}

// Ascending 構造 LessFunc 用於升序排序
//
//	arr := []uint32{3, 1, 4, 1, 5, 9}
//	List(arr).Sort(Ascending(arr))
func Ascending[T cmp.Ordered](list []T) LessFunc {
	return func(i, j int) bool {
		return list[i] < list[j]
	}
}

// Descending 構造 LessFunc 用於降序排序
//
//	arr := []uint32{3, 1, 4, 1, 5, 9}
//	List(arr).Sort(Descending(arr))
func Descending[T cmp.Ordered](list []T) LessFunc {
	return func(i, j int) bool {
		return list[i] > list[j]
	}
}

// Root 獲取根對象
func (list TList[T]) Root() []T {
	return list
}

// Distinct 移除重複元素, 原始對象不可用
func (list TList[T]) Distinct() (res TList[T]) {
	set := Set[T](nil)
	// 初始化切片空間
	res = list
	// 接受值下標
	// 值可接受時, 寫入到 accepted 處, 並使 accepted 前移
	accepted := 0
	for i, value := range list {
		if _, ok := set[value]; ok {
			// 已出現過, 忽略之
		} else {
			// 未出現過, 記録之
			if accepted != i {
				res[accepted] = list[i]
			}
			accepted++
			set[value] = Zero
		}
	}
	return res[:accepted]
}

// ToSet 轉換爲集合
func (list TList[T]) ToSet() (set TMap[T, ZeroStruct]) {
	set = Set[T](nil)
	for _, value := range list {
		if _, ok := set[value]; !ok {
			set[value] = Zero
		}
	}
	return
}

// 對列表排序, 包裝 sort.Slice
func (list TList[T]) Sort(less LessFunc) TList[T] {
	sort.Slice(list, less)
	return list
}

// 對列表排序, 包裝 sort.SliceStable
func (list TList[T]) SortStable(less LessFunc) TList[T] {
	sort.SliceStable(list, less)
	return list
}
